home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr46 / strx221.zip / STR.CPP < prev    next >
C/C++ Source or Header  |  1993-05-18  |  24KB  |  926 lines

  1. //
  2. // str.cpp : str class implementation
  3. // Author  : Roy S. Woll
  4. //
  5. // Copyright (c) 1993 by Roy S. Woll
  6. // You may distribute this source freely as long as you leave all files
  7. // in their original form, including the copyright notice as is.
  8. //
  9. //
  10. // Version 2.2          5/12/93
  11. //    Fixed substr assignment problem.  -->  str = substr
  12. //    Add member function read, lowercase,
  13. //    uppercase, and variations of pad and strip.
  14. // 
  15. // Version 2.11     3/17/93
  16. //    Friend operator ">>" changed to use str's buffer if > 256.
  17. //    Assign operator optimized to not copy referenced data.
  18. //    Fix - Remove member function now transfers only necessary characters
  19. //
  20. // Version 2.00     12/5/92
  21. //    Support searching/replacing, regular expressions, case sensitivity
  22. //
  23. //    Fixed the following bugs.
  24. //       1. Fixed size strings
  25. //       2. Concatenating a substr
  26. //
  27. //    Changed member functions pad/strip to modify instance, and introduced
  28. //    friend functions pad/strip.
  29. //
  30. // Version 1.00     10/20/92
  31. //
  32. #include <ctype.h>
  33. #include <string.h>
  34. #include <iostream.h>
  35. #include <iomanip.h>
  36. #include <assert.h>
  37.  
  38. #include "str.h"
  39. #include "dynstream.h"
  40.  
  41. int strnicmp(const char * s1, const char * s2, unsigned n);
  42. int stricmp(const char * s1, const char * s2);
  43. char * strlwr(char *);
  44. char * strupr(char *);
  45.  
  46. inline int min(int x, int y){if (x<y) return x; else return y;}
  47. inline int max(int x, int y){if (x>y) return x; else return y;}
  48.  
  49. // Define macro used to adjust internal debugging counters for object
  50. #ifdef DEBUG_STR     
  51. #define STR_SUB_COUNTERS(count)   count--;
  52. #define STR_ADD_COUNTERS(count)   count++;Total##count++;
  53. #else
  54. #define STR_SUB_COUNTERS(count)
  55. #define STR_ADD_COUNTERS(count)
  56. #endif
  57.  
  58.  
  59. static str::strdata NullData = {0, 0, 1, 0, 1, ""};
  60.  
  61. // Create and map to new buffer, and if previous buffer exists,
  62. //   transfer to new buffer.
  63. // Delete old buffer if unreferenced.
  64. char * str::getNewBuffer(int newbufsize){
  65.    return  getNewBuffer(length(), newbufsize);
  66. };
  67.  
  68. char * str::getNewBuffer(int len, int newbufsize)
  69. {
  70.    if (data==&NullData){
  71.      if (memsize_incr) newbufsize = max(newbufsize, memsize_init);
  72.      else newbufsize = memsize_init;
  73.    }
  74.    else {
  75.      if (!memsize_incr) return NULL;
  76.      if ((newbufsize>data->cursize) || (!newbufsize) )
  77.         newbufsize = max(newbufsize, data->cursize + memsize_incr);
  78.      else newbufsize = max(newbufsize, memsize_init);
  79.    }
  80.    if (!newbufsize) newbufsize = memsize_incr;       // don't allow 0 size
  81.  
  82.    strdata * newdata;
  83.    init(newdata, newbufsize, 0);
  84.    setNewBuffer(newdata, newbufsize, len);
  85.  
  86.    return data->buf;
  87. };
  88.  
  89. // Map to new buffer and if previous buffer exists, transfer to new buffer
  90. void str::setNewBuffer(strdata * newdata,
  91.            int newbufsize, int len){
  92.  
  93.    newdata->curlength = data->curlength;
  94.    newdata->strChange = data->strChange;
  95.  
  96.  
  97.    if (data->mystream) {
  98.  
  99.      // Use existing stream
  100.       newdata->mystream = data->mystream;
  101.  
  102.      // update existing stream to map to new buffer
  103.       newdata->mystream->rdbuf()->setNewBuffer(newdata->buf, newbufsize);
  104.  
  105.      // update stream length next time stream is called for previous data
  106.       if (!data->strChange){
  107.          data->strChange = 1;
  108.          data->curlength = data->mystream->rdbuf()->out_waiting();
  109.       };
  110.  
  111.      // force previous data to have unitialized stream
  112.       data->mystream = NULL;
  113.    };
  114.  
  115.    memcpy(newdata->buf, data->buf, len);
  116.  
  117.    if (!(--data->refcount)) {
  118.         delete data;
  119.         STR_SUB_COUNTERS(AllocationCount)
  120.    }
  121.  
  122.  
  123.    data = newdata;
  124. };
  125.  
  126.  
  127. void str::init(strdata*& adata, int cursize,
  128.           int curlength)
  129. {
  130.    STR_ADD_COUNTERS(AllocationCount)
  131.    if (!cursize) cursize=STR_DEFAULT_MEMINCR;
  132.  
  133.    adata =
  134.       (strdata *) new char [(cursize+1)+
  135.                             sizeof(strdata)-strdata::STR_DEBUG_BUFSIZE];
  136.    if (!adata){
  137.       cout << "Failed to allocate memory (" << cursize << ")" << endl;
  138.       assert(adata);
  139.    };
  140.  
  141.    adata->cursize=cursize;
  142.    adata->curlength=curlength;
  143.    adata->refcount=1;
  144.    adata->mystream=NULL;
  145.    adata->strChange=1;
  146. };
  147.  
  148.  
  149. // Construct an empty str
  150. str::str (void):
  151.           data(&NullData),
  152.           memsize_init(0), memsize_incr(STR_DEFAULT_MEMINCR),
  153.           flags(defaultFlags)
  154. {
  155.    STR_ADD_COUNTERS(ObjectCount)
  156.    data->refcount++;
  157. };
  158.  
  159. // Construct an empty str
  160. str::str (int p_bufsize, int p_incr):
  161.           data(&NullData),
  162.           memsize_init(p_bufsize), memsize_incr(p_incr),
  163.           flags(defaultFlags)
  164. {
  165.    STR_ADD_COUNTERS(ObjectCount)
  166.    data->refcount++;
  167. };
  168.  
  169.  
  170. // Construct a str containing substr, char *
  171. str::str (const char * s1, const char * s2):
  172.           memsize_init(0),memsize_incr(STR_DEFAULT_MEMINCR),
  173.           flags(defaultFlags)
  174. {
  175.  
  176.    STR_ADD_COUNTERS(ObjectCount)
  177.    int len1=(s1 ? strlen(s1) : 0);
  178.    int len2=(s2 ? strlen(s2) : 0);
  179.  
  180.    init(data, len1+len2, len1+len2);
  181.    memcpy(data->buf, s1, len1);
  182.    memcpy(data->buf+len1, s2, len2);
  183. };
  184.  
  185. // Construct a str containing char *, substr
  186. str::str (const char * s1, const substr& s2):
  187.           memsize_init(0),memsize_incr(STR_DEFAULT_MEMINCR),
  188.           flags(defaultFlags)
  189. {
  190.  
  191.    STR_ADD_COUNTERS(ObjectCount)
  192.    int len1=(s1 ? strlen(s1) : 0);
  193.    int len2=s2.length();
  194.  
  195.    init(data, len1+len2, len1+len2);
  196.    memcpy(data->buf, s1, len1);
  197.    memcpy(data->buf+len1, &s2.mystr->data->buf[s2.posReplace], len2);
  198. };
  199.  
  200. // Construct a str containing two char *
  201. str::str (const substr& s1, const char * s2):
  202.           memsize_init(0),memsize_incr(STR_DEFAULT_MEMINCR),
  203.           flags(defaultFlags)
  204. {
  205.  
  206.    STR_ADD_COUNTERS(ObjectCount)
  207.    int len1= s1.length();
  208.    int len2= (s2 ? strlen(s2) : 0);
  209.  
  210.    init(data, len1+len2, len1+len2);
  211.    memcpy(data->buf, &s1.mystr->data->buf[s1.posReplace], len1);
  212.    memcpy(data->buf+len1, s2, len2);
  213. };
  214.  
  215. // Construct a str containing two substr
  216. str::str (const substr& s1, const substr& s2):
  217.           memsize_init(0),memsize_incr(STR_DEFAULT_MEMINCR),
  218.           flags(defaultFlags)
  219. {
  220.  
  221.    STR_ADD_COUNTERS(ObjectCount)
  222.    int len1= s1.length();
  223.    int len2= s2.length();
  224.  
  225.    init(data, len1+len2, len1+len2);
  226.    memcpy(data->buf,      &s1.mystr->data->buf[s1.posReplace], len1);
  227.    memcpy(data->buf+len1, &s2.mystr->data->buf[s2.posReplace], len2);
  228. };
  229.  
  230. // Construct a str containing char *
  231. str::str (const char * s, int p_bufsize, int p_incr):
  232.           memsize_init(p_bufsize),memsize_incr(p_incr),
  233.           flags(defaultFlags)
  234. {
  235.    STR_ADD_COUNTERS(ObjectCount)
  236.    if (!s) return;
  237.  
  238.    int curlength, cursize;
  239.  
  240.    if (memsize_incr==0) {  // not allowed to expand
  241.       curlength = min(strlen(s), memsize_init);
  242.       cursize = memsize_init;
  243.    }
  244.    else {
  245.       curlength=strlen(s);
  246.       cursize = max(curlength, memsize_init);
  247.    };
  248.  
  249.    init(data, cursize, curlength);
  250.    memcpy(data->buf, s, curlength);
  251. };
  252.  
  253. // Construct a str containing str
  254. str::str (const str& s, int p_bufsize, int p_incr):
  255.           memsize_init(p_bufsize),memsize_incr(p_incr),
  256.           flags(defaultFlags)
  257. {
  258.    STR_ADD_COUNTERS(ObjectCount)
  259.  
  260.    if (memsize_incr) {
  261.       data = s.data;
  262.       data->refcount++;
  263.    }
  264.    else {
  265.       int curlength = min(s.length(), memsize_init);
  266.       init(data, memsize_init, curlength);
  267.       memcpy(data->buf, s, curlength);
  268.    };
  269.  
  270. };
  271.  
  272.  
  273. // Return a ostream that maps to the same buffer as the str
  274. ostream& str::stream(int pos){
  275.    return stream().seekp(pos);
  276. };
  277.  
  278. // Return a ostream that maps to the same buffer as the str
  279. ostream& str::stream(void){
  280.  
  281.   //
  282.   // check if need to allocate more memory
  283.   //
  284.    int allocsize=0;
  285.    if (data==&NullData) allocsize = memsize_init;    // first time allocating
  286.    else if (length()>=size()) allocsize = size()+memsize_incr;
  287.    _checkMemAllocation(allocsize);
  288.  
  289.   //
  290.   // Create stream if it doesn't exist
  291.   // otherwise tell dynstream about me in case it needs to extend buf
  292.   //
  293.    if (!data->mystream) data->mystream = new dynstream(this);
  294.    else data->mystream->rdbuf()->set_str(this);
  295.  
  296.  
  297.   //
  298.   // update stream length if length has been changed by str operators.
  299.   // Not done every time in case stream operation was the last operation 
  300.   // to change the length.
  301.   //
  302.    if (data->strChange) {
  303.        data->mystream->rdbuf()->set_len(data->curlength);
  304.        data->strChange=0;
  305.    };
  306.    return *data->mystream;
  307. };
  308.  
  309. int str::length(void) const{
  310.    if ((!data->strChange) && (data->mystream))
  311.       setlength(data->mystream->rdbuf()->out_waiting());
  312.  
  313.    return data->curlength;
  314. };
  315.  
  316. str::~str (void){
  317.    STR_SUB_COUNTERS(ObjectCount)
  318.  
  319.    if (!(--data->refcount)){
  320.       STR_SUB_COUNTERS(AllocationCount)
  321.  
  322.       delete data->mystream;
  323.       delete data;
  324.    };
  325. };
  326.  
  327. //
  328. // return (const char *)
  329. //
  330. str::operator const char * () const{
  331.    data->buf[length()] = 0;
  332.    return data->buf;
  333. };
  334.  
  335. const char * str::operator()(int index) const   
  336. {
  337.    return  (*this)() + index;
  338. }
  339.  
  340. char& str::operator[](int position)   // array indexing
  341. {
  342.    if (data->refcount>1) getNewBuffer(data->cursize);
  343.  
  344.    #ifndef SMART_STR_USER
  345.    //
  346.    // Force string to be null-terminated in case user
  347.    //   uses the "&" operator to pass a pointer (ie. &mystr[3])
  348.    //
  349.    if (!data->strChange) return *(char *)(*this)(position);
  350.          
  351.    #endif
  352.          
  353.    
  354.    return data->buf[position];
  355. }
  356.  
  357. int str::size(void) const{
  358.    return data->cursize;
  359. };
  360.                  
  361. //
  362. // str member = operators
  363. //
  364. str & str::_assign(const char * s, int len)
  365. {
  366.   // Get new buffer if necessary, but don't transfer contents.
  367.   // This is handled specially, so as to remove the unnecessary transfer.
  368.    if ((data->refcount>1) || (size()<len)) 
  369.       getNewBuffer( 0, max(size(),len) );
  370.  
  371.    if (!memsize_incr) len = min(len, size());
  372.    memcpy(data->buf, s, len);
  373.    setlength(len);
  374.    return *this;
  375.  
  376. };
  377.  
  378. str& str::operator = (const str& s){
  379.    if (this == &s) return *this;         // assignment to self
  380.    if (data == s.data) return *this;     // assignment to self
  381.  
  382.    if (!memsize_incr) return _assign(s, s.length());
  383.  
  384.    dynstream * prevStream=NULL;
  385.  
  386.    if (!(--data->refcount)) {  // deallocate old pointer
  387.       STR_SUB_COUNTERS(AllocationCount)
  388.  
  389.      //
  390.      // try to reuse this stream
  391.      //
  392.       prevStream = data->mystream;
  393.       if (s.data){
  394.          if (s.data->mystream) {
  395.             delete data->mystream;
  396.             prevStream = NULL;
  397.          }
  398.       }
  399.  
  400.       delete data;
  401.    };
  402.  
  403.    data = s.data;
  404.  
  405.    data->refcount++;
  406.  
  407.   //
  408.   // Map my stream to point to an existing stream using buffer data->buf
  409.   //
  410.    if (prevStream) {
  411.  
  412.          data->mystream = prevStream;  // what about previous mystream?
  413.  
  414.         //
  415.         // update s stream to map to new this stream
  416.         //
  417.          data->mystream->rdbuf()->setNewBuffer(data->buf, size());
  418.  
  419.         //
  420.         // update stream length next time stream is called for previous data
  421.         //
  422.          data->strChange = 1;
  423.  
  424.    }
  425.  
  426.  
  427.    return *this;
  428.  
  429. };
  430.  
  431.  
  432. str& str::operator = (const substr& s){
  433.    
  434.     int len = s.mystr->length() - s.posReplace;
  435.    if (len>=0) len = min(s.numReplace, len);
  436.    return _assign((*s.mystr)(s.posReplace), len);
  437. };
  438.  
  439. str& str::operator = (const char * s){
  440.    return _assign(s, strlen(s));
  441. };
  442.  
  443. str& str::assign(const char * s, int len){
  444.    return _assign(s, min(strlen(s), len));
  445. };
  446.  
  447. str& str::operator = (const char s){
  448.    return _assign(&s, 1);
  449. };
  450.  
  451. str & str::_concat(const char * s, int len)
  452. {
  453.    int mylen = length();
  454.  
  455.    _checkMemAllocation(mylen + len);
  456.  
  457.    if (!memsize_incr) len = min(len, size()-mylen);
  458.    memcpy(data->buf + mylen, s, len);    //concat
  459.    setlength(mylen+len);
  460.    return *this;
  461.  
  462. };
  463.  
  464.  
  465. //
  466. // str member += operators
  467. //
  468. str & str::operator += (const str& s){
  469.    if (!length()) return *this=s;
  470.    return _concat(s, s.length());
  471. };
  472.  
  473. str & str::operator += (const substr& s){
  474.    return _concat(&s.mystr->data->buf[s.posReplace], s.length());
  475. };
  476.  
  477. str & str::operator += (const char * s){
  478.    return _concat(s, strlen(s));
  479. };
  480.  
  481. str & str::operator += (const char s){
  482.    return _concat(&s, 1);
  483. };
  484.  
  485.  
  486. //
  487. // str member << operators
  488. //
  489. str& str::operator << (const str& s)    { return *this+=s;};
  490. str& str::operator << (const substr& s) { return *this+=s;};
  491. str& str::operator << (const char * s)  { return *this+=s;};
  492. str& str::operator << (const char s)    { return *this+=s;};
  493. str& str::operator << (const int s){
  494.    stream() << s;
  495.    return *this;
  496. };
  497.  
  498. //
  499. // str member + operators
  500. //
  501. str str::operator+(const _SUBSTR & b) const{ return str(*this,b); };
  502. str str::operator+(const str&b)           const{ return str(*this,b); };
  503. str str::operator+(const char * b)        const{ return str(*this,b); };
  504. str str::operator+(const char b) const{
  505.    char buf[2];
  506.    buf[0]=b;
  507.    buf[1]=0;
  508.  
  509.    return str(*this,buf);
  510. };
  511.  
  512.  
  513. // 
  514. // istream/ostream friend functions
  515. //
  516. istream& operator >> (istream& stream, str & s){
  517.    if (s.memsize_init>256){   // Use str's current data buffer
  518.       s = " ";                // Gets new buffer if neccessary (ie. reference)
  519.       stream.getline(s.data->buf, s.size());
  520.       s.setlength(stream.gcount());
  521.       if (s[s.length()]==10)  // retrieve to end of line
  522.          s.setlength(s.length()-1);
  523.    }
  524.    else {
  525.       char buf[256];
  526.       stream.getline(buf, 256);
  527.       if (buf[stream.gcount()-1]==10)  // retrieve to end of line
  528.          buf[stream.gcount()-1]=0;
  529.  
  530.       s = buf;
  531.    };
  532.  
  533.    return stream;
  534. };
  535.  
  536. istream& str::read(istream& stream, int count)
  537. {
  538.     *this = " ";         // Gets new buffer if neccessary (ie. reference)
  539.     stream.read(data->buf, min(size(), count));
  540.    setlength(stream.gcount());
  541.  
  542.    return stream;
  543. };
  544.  
  545. ostream& operator << (ostream& stream, const str & s){
  546.    return stream << s();
  547. };
  548.  
  549.  
  550. str& str::lowercase()
  551. {
  552.   _checkMemAllocation();
  553.   strlwr(data->buf);
  554.   return *this;
  555. }
  556.  
  557. str& str::uppercase()
  558. {
  559.   _checkMemAllocation();
  560.   strupr(data->buf);
  561.   return *this;
  562. }
  563.  
  564. //
  565. // uppercase/lowercase friend functions
  566. //
  567. str uppercase(const char * s) {
  568.    str newstr(s);
  569.    strupr((char *)newstr());
  570.    return newstr;
  571. };
  572.  
  573. str lowercase(const char * s) {
  574.    str newstr(s);
  575.    strlwr((char *)newstr());
  576.    return newstr;
  577. };
  578.  
  579.  
  580. //
  581. // pad/strip
  582. //
  583. str& str::padRight(int padsize, char padchar)
  584.    return pad(padsize, right, padchar);
  585. }
  586. str& str::padLeft(int padsize, char padchar)
  587.    return pad(padsize, left, padchar);
  588. }
  589. str& str::padBoth(int padsize, char padchar)
  590.    return pad(padsize, both, padchar);
  591. }
  592.  
  593. str& str::pad(int padsize, PadStripT t, char padchar){
  594.  
  595.    int len = length();
  596.  
  597.    if (len<padsize) {
  598.  
  599.       _checkMemAllocation(padsize);
  600.       if (!memsize_incr) padsize = min(padsize, size());
  601.       
  602.       if (t == right)
  603.          memset(&data->buf[len], padchar, padsize-len);
  604.  
  605.       else if (t == both){
  606.          int len1 = (padsize-len)/2;
  607.          int len2 = (padsize-len+1)/2;
  608.  
  609.          memmove(&data->buf[len1], &data->buf, len);
  610.          memset(&data->buf[0], padchar, len1);
  611.          memset(&data->buf[len+len1], padchar, len2);
  612.       }
  613.  
  614.       else{
  615.          int len1 = (padsize-len);
  616.  
  617.          memmove(&data->buf[len1], &data->buf, len);
  618.          memset(&data->buf[0], padchar, len1);
  619.       }
  620.  
  621.       setlength(padsize);
  622.    };
  623.  
  624.    return *this;
  625. }
  626.  
  627. str& str::stripTrailing(const char * stripchars)
  628. {
  629.    return strip(trailing, stripchars);
  630. }
  631. str& str::stripLeading(const char * stripchars)
  632. {
  633.    return strip(leading, stripchars);
  634. }
  635. str& str::stripBoth(const char * stripchars)
  636. {
  637.    return strip(both, stripchars);
  638. }
  639. str& str::strip(PadStripT t, char stripchar){
  640.  
  641.    int len = length();
  642.    int start = 0;
  643.    int end = len-1;
  644.  
  645.    if (end<0) return *this;
  646.  
  647.    if ((t == leading) || (t==both)){
  648.       for (; start<=end; start++)
  649.          if (data->buf[start] != stripchar) break;
  650.    };
  651.  
  652.    if ((t == trailing) || (t==both)){
  653.        if (data->buf[end] == stripchar) {
  654.           for (; end >= start; end--){
  655.              if (data->buf[end] != stripchar) break;
  656.           };
  657.        };
  658.    };
  659.  
  660.    if ((end-start+1)<len)
  661.    {
  662.       _checkMemAllocation();
  663.       if (start) memmove(&data->buf[0], &data->buf[start], end-start+1);
  664.       setlength(end-start+1);
  665.    };
  666.  
  667.    return *this;
  668.  
  669. };
  670.  
  671.  
  672. str& str::strip(PadStripT t, const char * stripchars){
  673.  
  674.    int len = length();
  675.    int start = 0;
  676.    int end = len-1;
  677.  
  678.    if (end<0) return *this;
  679.  
  680.  
  681.    if ((t == leading) || (t==both)){
  682.  
  683.       int pos = strspn((*this)(), stripchars);
  684.       if (pos>0) start += pos;
  685.  
  686.    };
  687.  
  688.    if ((t == trailing) || (t==both)){
  689.  
  690.      if (strchr(stripchars, data->buf[end])){
  691.         for (; end>=start; end--){
  692.            if (!strchr(stripchars, data->buf[end])) break;
  693.         }
  694.      }
  695.    };
  696.  
  697.    if ((end-start+1)<len)
  698.    {
  699.       _checkMemAllocation();
  700.       if (start) memmove(&data->buf[0], &data->buf[start], end-start+1);
  701.       setlength(end-start+1);
  702.    };
  703.  
  704.    return *this;
  705. };
  706.  
  707. str pad(str s, int padsize, str::PadStripT t, char padchar){
  708.    return s.pad(padsize, t, padchar);
  709. };
  710.  
  711. str strip(str s, str::PadStripT t, const char * stripchars){
  712.    return s.strip(t, stripchars);
  713. };
  714.  
  715. str strip(str s, str::PadStripT t, char stripchar){
  716.    return s.strip(t, stripchar);
  717. };
  718.  
  719.  
  720. //
  721. // insert/remove
  722. //
  723. int str::insert(int pos, char ch){
  724.     char tempstr[2];
  725.     tempstr[0] = ch;
  726.     tempstr[1] = 0;
  727.     return insert(pos, tempstr);
  728. }
  729.  
  730. int str::insert(int pos, const char * insertStr){
  731.    int len = length();
  732.    int afterPos = len+1-pos;  // number of characters following pos
  733.  
  734.    if (afterPos<0) return 0;  // out of range
  735.  
  736.    int insertLen = strlen(insertStr);
  737.    _checkMemAllocation( len+insertLen );
  738.  
  739.    if (!memsize_incr) insertLen = min(insertLen, size()-len);
  740.  
  741.    if (insertLen){
  742.      if (afterPos)
  743.         memmove(&data->buf[pos + insertLen], &data->buf[pos], afterPos);
  744.      memmove(&data->buf[pos], insertStr, insertLen);
  745.      setlength(len+insertLen);
  746.      return 1;
  747.    }
  748.    else return 0;
  749. };
  750.  
  751. void str::remove(int pos, int numdel){
  752.    int len = length();
  753.    if (pos>=len) return;
  754.    _checkMemAllocation();
  755.  
  756.    numdel = min(numdel, len-pos); 
  757.    memmove(&data->buf[pos], &data->buf[pos+numdel], len-(numdel+pos));
  758.    setlength(len-numdel);
  759. };   
  760.  
  761.  
  762. //
  763. // substr member operators/functions
  764. //
  765. _SUBSTR::substr(const str * data, int AposReplace, int AnumReplace):
  766.    mystr((str *)data), posReplace(AposReplace), numReplace(AnumReplace){};
  767.  
  768. _SUBSTR str::operator()(int pos, int numreplace)
  769. {
  770.    return substr(this, pos, numreplace);
  771. }
  772.  
  773. const _SUBSTR str::operator()(int pos, int numreplace) const
  774. {
  775.    return substr(this, pos, numreplace);
  776. }
  777.  
  778. int _SUBSTR::length(void) const{
  779.    return min(numReplace, max(0, mystr->length()-posReplace) );
  780. };
  781.  
  782.  
  783. str & _SUBSTR::operator = (const char * s){
  784.    if (posReplace<0) return *this->mystr;
  785.  
  786.    if (strlen(s)==length()){
  787.       mystr->_checkMemAllocation();
  788.       memcpy(&mystr->data->buf[posReplace], s, length());
  789.    }
  790.    else {
  791.       mystr->remove(posReplace, numReplace);
  792.       mystr->insert(posReplace, s);
  793.    };
  794.    return *this->mystr;
  795. };
  796.  
  797. str & _SUBSTR::operator = (const substr& s){
  798.    return *this = *s.mystr;
  799. };
  800.  
  801. str _SUBSTR::operator+(const char * s) const{
  802.    return str(*this, s);
  803. };
  804.  
  805. str _SUBSTR::operator+(const substr& s) const{
  806.    return str(*this, s);
  807. };
  808.  
  809. int _SUBSTR::compare(const char * s) const{
  810.    return mystr->strncmp((*this->mystr)(posReplace), s, numReplace);
  811. };
  812.  
  813. int _SUBSTR::compare(const substr& s) const{
  814.    int len = min(numReplace, s.numReplace);
  815.    return mystr->strncmp((*this->mystr)(posReplace), (*s.mystr)(s.posReplace), len);
  816. };
  817.  
  818. int _SUBSTR::operator==(const char *s) const{ return compare(s)==0; };
  819. int _SUBSTR::operator<=(const char *s) const{ return compare(s)<=0; };
  820. int _SUBSTR::operator>=(const char *s) const{ return compare(s)>=0; };
  821. int _SUBSTR::operator!=(const char *s) const{ return compare(s)!=0; };
  822. int _SUBSTR::operator< (const char *s) const{ return compare(s)< 0; };
  823. int _SUBSTR::operator> (const char *s) const{ return compare(s)> 0; };
  824.  
  825. int _SUBSTR::operator==(const substr& s) const{ return compare(s)==0; };
  826. int _SUBSTR::operator<=(const substr& s) const{ return compare(s)<=0; };
  827. int _SUBSTR::operator>=(const substr& s) const{ return compare(s)>=0; };
  828. int _SUBSTR::operator!=(const substr& s) const{ return compare(s)!=0; };
  829. int _SUBSTR::operator< (const substr& s) const{ return compare(s)< 0; };
  830. int _SUBSTR::operator> (const substr& s) const{ return compare(s)> 0; };
  831.  
  832. _SUBSTR::operator str() const{
  833.   str temp;
  834.   temp.assign((*(mystr))(posReplace), numReplace);
  835.   return temp;
  836. };
  837.  
  838. int str::_checkMemAllocation(int requiredLen){
  839.    if ((data->refcount<=1) && (size()>=requiredLen)) return 1;
  840.  
  841.    return (getNewBuffer(max(size(), requiredLen))!=NULL);
  842. };
  843.  
  844.  
  845. //
  846. // Case sensitivity member functions
  847. //
  848. int str::caseSensitive(void) const { return !(flags & ICASE); }
  849.  
  850. void str::setCaseSensitive(int val) 
  851.   if (val) flags &= !ICASE;
  852.   else flags |= ICASE; 
  853. }
  854.  
  855. void str::setdefaultCaseSensitive(int val)
  856. {
  857.   if (val) defaultFlags &= !ICASE;
  858.   else defaultFlags |= ICASE; 
  859. }
  860.  
  861. //
  862. // Friend/Global str relational operators
  863. //
  864. str operator + (const char *a, const str&b)        {  return str(a,b); };
  865. str operator + (const char *a, const _SUBSTR&b){  return str(a,b); };
  866.  
  867. int compare(const char * a, const str & b) {return ( b.strcmp(a, b) );};
  868. int compare(const str& a,   const str & b) {return ( a.strcmp(a, b) );};
  869. int compare(const str& a,  const char * b) {return ( a.strcmp(a, b) );};
  870.  
  871. int operator ==(const char *a, const str&b){return (compare(a,b) == 0); };
  872. int operator >=(const char *a, const str&b){return (compare(a,b) >= 0); };
  873. int operator <=(const char *a, const str&b){return (compare(a,b) <= 0); };
  874. int operator !=(const char *a, const str&b){return (compare(a,b) != 0); };
  875. int operator > (const char *a, const str&b){return (compare(a,b) > 0); };
  876. int operator < (const char *a, const str&b){return (compare(a,b) < 0);};
  877.  
  878. int operator ==(const char *a, const _SUBSTR &b){ return b==a; };
  879. int operator >=(const char *a, const _SUBSTR &b){ return b<=a; };
  880. int operator <=(const char *a, const _SUBSTR &b){ return b>=a; };
  881. int operator !=(const char *a, const _SUBSTR &b){ return b!=a; };
  882. int operator > (const char *a, const _SUBSTR &b){ return b<a;  };
  883. int operator < (const char *a, const _SUBSTR &b){ return b>a;  };
  884.  
  885. //
  886. // Member str relational operators
  887. //
  888. int str::operator==(const char *b) const{ return (compare(*this,b) == 0); };
  889. int str::operator<=(const char *b) const{ return (compare(*this,b) <= 0); };
  890. int str::operator>=(const char *b) const{ return (compare(*this,b) >= 0); };
  891. int str::operator!=(const char *b) const{ return (compare(*this,b) != 0); };
  892. int str::operator> (const char *b) const{ return (compare(*this,b) > 0); };
  893. int str::operator< (const char *b) const{ return (compare(*this,b) < 0); };
  894.  
  895. int str::operator==(const str &b) const{ return (compare(*this,b) == 0); };
  896. int str::operator<=(const str &b) const{ return (compare(*this,b) <= 0); };
  897. int str::operator>=(const str &b) const{ return (compare(*this,b) >= 0); };
  898. int str::operator!=(const str &b) const{ return (compare(*this,b) != 0); };
  899. int str::operator> (const str &b) const{ return (compare(*this,b) > 0); };
  900. int str::operator< (const str &b) const{ return (compare(*this,b) < 0); };
  901.  
  902.  
  903. int str::strncmp(const char * s1, const char * s2, int n) const{
  904.    if (caseSensitive()) return ::strncmp(s1,s2,n);
  905.    else return ::strnicmp(s1,s2,n);
  906. };
  907.  
  908. int str::strcmp(const char * s1, const char * s2) const{
  909.    if (caseSensitive()) return ::strcmp(s1,s2);
  910.    else return ::stricmp(s1,s2);
  911. };
  912.  
  913. int str::defaultFlags = 0;
  914.  
  915. #ifdef DEBUG_STR
  916. int str::dynstreamCount=0;
  917. int str::ObjectCount=0;
  918. int str::AllocationCount=0;
  919. int str::TotalObjectCount=0;
  920. int str::TotalAllocationCount=0;
  921. #endif
  922.